package jp.co.hcs.attendancemanagement.inputdailyattendance.logic;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import jp.co.hcs.attendancemanagement.AMConstants;
import jp.co.hcs.attendancemanagement.AMResourceKeyConstants;
import jp.co.hcs.attendancemanagement.AMResourceManager;
import jp.co.hcs.attendancemanagement.StrutsMessageConstants;
import jp.co.hcs.attendancemanagement.data.entity.Job;
import jp.co.hcs.attendancemanagement.data.entity.PerformanceStamp;
import jp.co.hcs.attendancemanagement.data.entity.SubstituteHolidayActual;
import jp.co.hcs.attendancemanagement.data.entity.WorkMessage;
import jp.co.hcs.attendancemanagement.data.entity.WorkingTimeActual;
import jp.co.hcs.attendancemanagement.data.entity.WorkingTimeMaster;
import jp.co.hcs.attendancemanagement.data.entity.ex.EffortActualParameter;
import jp.co.hcs.attendancemanagement.inputdailyattendance.actionform.InputDailyAttendanceForm;
import jp.co.hcs.attendancemanagement.inputdailyattendance.logic.dto.DailyWorkingActualResultDTO;
import jp.co.hcs.attendancemanagement.inputdailyattendance.logic.dto.EmployeeCompanyDTO;
import jp.co.hcs.attendancemanagement.inputdailyattendance.logic.dto.ProjectInfoDTO;
import jp.co.hcs.attendancemanagement.inputdailyattendance.logic.dto.StampActualResultDTO;
import jp.co.hcs.attendancemanagement.util.DateUtil;
import jp.co.hcs.attendancemanagement.util.StringUtil;

import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.util.LabelValueBean;

/**
 * The Class InputDailyAttendanceLogic.
 */
public class InputDailyAttendanceLogic extends InputDailyWorkingLogicBase {

  /** The input daily attendance logic. */
  private static InputDailyAttendanceLogic inputDailyAttendanceLogic =
      new InputDailyAttendanceLogic();

  /**
   * Gets the single instance of InputDailyAttendanceLogic.
   * 
   * @return single instance of InputDailyAttendanceLogic
   */
  public static InputDailyAttendanceLogic getInstance() {
    return inputDailyAttendanceLogic;
  }

  /**
   * Gets the employee company info dto.
   * 
   * @param employeeId the employee id
   * @return the employee company info dto
   * @throws SQLException the sQL exception
   */
  public EmployeeCompanyDTO getEmployeeCompanyInfoDTO(String employeeId) throws SQLException {
    return getEmployeeMasterDAO().getEmployeeCompanyInfoDTO(employeeId);
  }
  
  /**
   * Gets the daily working time info.
   * 
   * @param employeeId the employee id
   * @param yearMonth the year month
   * @param day the day
   * @return the daily working time info
   * @throws SQLException the sQL exception
   */
  public DailyWorkingActualResultDTO getDailyWorkingTimeInfo(String employeeId, String yearMonth,
      String day) throws SQLException {
    WorkingTimeActual workingTimeActual =
        getWorkingTimeActualDAO().selectWorkingTimeActualByPrimaryKey(employeeId, day, yearMonth);
    DailyWorkingActualResultDTO timeDTO = new DailyWorkingActualResultDTO();

    if (workingTimeActual != null) {
      timeDTO.setDailyWorkingApprovalStatus(workingTimeActual.getApprovalStatus());
      timeDTO.setPlannedWorkingStartTime(DateUtil.convertDateToHourFormat(workingTimeActual
          .getWorkingPlannedStartTime()));
      timeDTO.setPlannedWorkingEndTime(DateUtil.convertDateToHourFormat(workingTimeActual
          .getWorkingPlannedEndTime()));
      timeDTO.setJobDivision(workingTimeActual.getJobId());
      timeDTO.setWorkingStartTime(DateUtil.convertDateToHourFormat(workingTimeActual
          .getWorkingStartTime()));
      timeDTO.setWorkingStartDay(DateUtil.convertDate(workingTimeActual.getWorkingStartDay()));
      timeDTO.setWorkingEndDay(DateUtil.convertDate(workingTimeActual.getWorkingEndDay()));
      timeDTO.setWorkingEndTime(DateUtil.convertDateToHourFormat(workingTimeActual
          .getWorkingEndTime()));
      timeDTO.setTimeDivision(workingTimeActual.getTimeType());
      timeDTO.setApplicationNo(workingTimeActual.getApplicationNo());
      timeDTO.setSubstituteHolidayNo(workingTimeActual.getAdditionalHolidayNo());
      timeDTO.setTakingVacationNo(workingTimeActual.getTakingVacationNo());
      timeDTO.setPaidHoliday(DateUtil.convertDateToHourFormat(workingTimeActual.getPaidHoliday()));
      timeDTO.setWorkingTime(DateUtil.convertDateToHourFormat(workingTimeActual.getWorkingTime()));
      timeDTO.setPlannedWorkingTime(DateUtil.convertDateToHourFormat(workingTimeActual
          .getWorkingPlannedTime()));
      timeDTO.setOvertimeAutomaticApply(DateUtil.convertDateToHourFormat(workingTimeActual
          .getOvertimeAutomaticApply()));
      timeDTO.setComingLateFlag(workingTimeActual.getIsComingLate());
      timeDTO.setLeavingEarlyFlag(workingTimeActual.getIsReturningEarly());
      timeDTO.setCommutingDelayFlag(workingTimeActual.getIsCommutingDelay());
      timeDTO.setRestTime(DateUtil.convertDateToHourFormat(workingTimeActual.getRestTime()));
      timeDTO.setComment(workingTimeActual.getComment());
      timeDTO.setFixedWorkingTime(DateUtil.convertDateToHourFormat(workingTimeActual
          .getWorkingFixTime()));
      timeDTO.setOvertime(DateUtil.convertDateToHourFormat(workingTimeActual.getOvertimeTime()));
      timeDTO.setNightWorkTime(DateUtil.convertDateToHourFormat(workingTimeActual
          .getNightWorkTime()));
      timeDTO.setSatWorkingTime(DateUtil.convertDateToHourFormat(workingTimeActual
          .getSaturdayWorkingTime()));
      timeDTO.setHolidayWorkTime(DateUtil.convertDateToHourFormat(workingTimeActual
          .getSundayAndHolidayWorkingTime()));
      timeDTO.setSubstituteHolidayTime(DateUtil.convertDateToHourFormat(workingTimeActual
          .getSubstituteHolidayWorkingTime()));
      timeDTO.setInsufficentTime(DateUtil.convertDateToHourFormat(workingTimeActual
          .getInsufficentWorkingTime()));
      timeDTO.setSatNightWorkTime(DateUtil.convertDateToHourFormat(workingTimeActual
          .getSaturdayMidnightWorkingTime()));
      timeDTO.setHolidayNightWorkTime(DateUtil.convertDateToHourFormat(workingTimeActual
          .getSundayAndHolidayMidnightWorkingTime()));
      timeDTO.setAnnouncement(workingTimeActual.getAnnouncement());
      timeDTO.setAddedSubstituteHolidayNo(workingTimeActual.getAdditionalHolidayNo());
      timeDTO.setTotalOvertimePerDay(DateUtil.convertDateToHourFormat(workingTimeActual
          .getTotalOvertimePerDay()));
      timeDTO.setNightShiftWork(DateUtil.convertDateToHourFormat(workingTimeActual
          .getMidnightShiftWorkingTime()));
    }

    return timeDTO;
  }

  /**
   * Gets the stamp actual result dto.
   * 
   * @param employeeId the employee id
   * @param yearMonth the year month
   * @param day the day
   * @return the stamp actual result dto
   * @throws SQLException the sQL exception
   */
  public StampActualResultDTO getStampActualResultDTO(String employeeId, String yearMonth,
      String day) throws SQLException {
    PerformanceStamp stampActual =
        getPerformanceStampDAO().selectPerformanceStampByPrimaryKey(employeeId, day, yearMonth);
    StampActualResultDTO dto = new StampActualResultDTO();
    if (stampActual != null) {
      dto.setChokkiFlag("1".equals(stampActual.getIsChokki()));
      dto.setChokkoFlag("1".equals(stampActual.getIsChokko()));
      dto.setComingWorkDay(DateUtil.convertDate(stampActual.getComingWorkDate()));
      dto.setComingWorkTime(DateUtil.convertDateToHourFormat(stampActual.getComingWorkTime()));
      dto.setLeavingWorkDay(DateUtil.convertDate(stampActual.getLeavingWorkDate()));
      dto.setLeavingWorkTime(DateUtil.convertDateToHourFormat(stampActual.getLeavingWorkTime()));
    }
    return dto;
  }

  /**
   * Gets the project info dto list.
   * 
   * @param effortActualParameter the effort actual parameter
   * @return the project info dto list
   * @throws SQLException the sQL exception
   */
  public List<ProjectInfoDTO> getProjectInfoDTOList(EffortActualParameter effortActualParameter)
      throws SQLException {
    return getEffortActualDAO().getProjectInfoDTOList(effortActualParameter);
  }

  /**
   * Inits the data for screen.
   * 
   * @param form the form
   * @throws SQLException the sQL exception
   */
  public ActionMessages initDataForScreen(InputDailyAttendanceForm form) throws SQLException {
    ActionMessages errors = new ActionMessages();
      
    String userId = form.getUserId();
    String currentYearMonth = form.getYear() + form.getMonth();
    String currentDay = form.getDay();

    // get data from stamp actual result
    form.setStampActualResultDTO(getStampActualResultDTO(userId, currentYearMonth, currentDay));

    // get data from daily working actual result
    DailyWorkingActualResultDTO dailyWorkingTimeInfo =
        getDailyWorkingTimeInfo(userId, currentYearMonth, currentDay);
    form.setTimeDTO(dailyWorkingTimeInfo);

    // get data overtime working per month
    String overtimeWorkingPerMonth =
        getWorkingTimeActualDAO().getOvertimeWorkingPerMonth(userId, currentYearMonth);
    if (!StringUtil.isEmpty(overtimeWorkingPerMonth)) {
      form.setOverTimeWorkingPerMonth(overtimeWorkingPerMonth);
    }
    // get data from daily effort actual
    EffortActualParameter effortActualParameter = new EffortActualParameter();
    effortActualParameter.setEmployerCode(userId);
    effortActualParameter.setSelectPeriod(currentYearMonth);
    effortActualParameter.setEffortActualDate(currentDay);
    List<ProjectInfoDTO> projectInfoDTO = getProjectInfoDTOList(effortActualParameter);
    form.setProjectInfoDTOList(projectInfoDTO);

    // get substitute planned holiday
    SubstituteHolidayActual sha =
        getSubstituteHolidayActualDAO().selectSubstituteHolidayActualByPrimaryKey(
            dailyWorkingTimeInfo.getAddedSubstituteHolidayNo());
    if (sha != null) {
      form.setSubstituteHoliday(DateUtil.convertDate(sha.getSubstituteHolidayPlannedDay()));
    }

    // phan dinh status
    boolean isEditable;
    if (StringUtil.EDITING_VALUE.equals(dailyWorkingTimeInfo.getDailyWorkingApprovalStatus())
        || StringUtil.BACK_VALUE.equals(dailyWorkingTimeInfo.getDailyWorkingApprovalStatus())
        || StringUtil.isEmpty(dailyWorkingTimeInfo.getDailyWorkingApprovalStatus())) {
      isEditable = true;
    } else {
      isEditable = false;
    }
    form.setIsEditable(isEditable);

    // get time classification
    WorkingTimeMaster timeMaster = null;
    if (StringUtil.isEmpty(dailyWorkingTimeInfo.getTimeDivision())) {
      timeMaster = getWorkingTimeMasterDAO().getAssignWorkingTimeMaster(form.getUserId(),
              DateUtil.parseDate(form.getMonth() + "/" + form.getDay(), form.getYear()));
      if (timeMaster != null) {
        dailyWorkingTimeInfo.setTimeDivision(timeMaster.getWorkingTimeId());
        dailyWorkingTimeInfo.setPlannedWorkingStartTime(DateUtil.convertDateToHourFormat(timeMaster
            .getStartTime()));
        dailyWorkingTimeInfo.setPlannedWorkingEndTime(DateUtil.convertDateToHourFormat(timeMaster
            .getEndTime()));
        String fixedWorkingTime =
            DateUtil.convertDateToHourFormat(timeMaster.getFixedWorkingTime());
        dailyWorkingTimeInfo.setPlannedWorkingTime(fixedWorkingTime);
        dailyWorkingTimeInfo.setOvertimeAutomaticApply(DateUtil.convertDateToHourFormat(timeMaster
            .getAutoOvertimeTime()));
      }
      else {
        //error message: time classification is not selected
        errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage(
                StrutsMessageConstants.ALARM_W1054_ERROR, AMResourceManager
                    .getMessage(AMResourceKeyConstants.FIELD_TIMECLASSIFICATION)));
      }
    }
    else {
      timeMaster = getWorkingTimeMasterDAO().selectWorkingTimeMasterByPrimaryKey(dailyWorkingTimeInfo.getTimeDivision());
    }

    // get announcement message
    if (!StringUtil.isEmpty(dailyWorkingTimeInfo.getAnnouncement())) {
      WorkMessage message =
          getWorkMessageDAO().selectWorkMessageByPrimaryKey(dailyWorkingTimeInfo.getAnnouncement());
      if (message != null) {
        form.setAnnouncement(message.getMessage());
      }
    }
    
    // get leave time
    String jobType = dailyWorkingTimeInfo.getJobDivision();
    String leaveTime = "00:00";
    if (!StringUtil.isEmpty(jobType) && timeMaster != null) {
      Job jobDivision = getJobDAO().selectJobByPrimaryKey(jobType);
      if (AMConstants.PAID_LEAVE.equals(jobDivision.getJobId())
          || AMConstants.SUBSTITUTE_LEAVE.equals(jobDivision.getJobId())) {
        leaveTime = DateUtil.convertDateToHourFormat(timeMaster.getFixedWorkingTime());
      } else if (AMConstants.HALF_MORNING_LEAVE.equals(jobDivision.getJobId())) {
        leaveTime = DateUtil.convertDateToHourFormat(timeMaster.getMorningRestTime());
      } else if (AMConstants.HALF_AFTERNOON_LEAVE.equals(jobDivision.getJobId())) {
        leaveTime = DateUtil.convertDateToHourFormat(timeMaster.getAfternoonRestTime());
      } else if (AMConstants.TIME_PAID_LEAVE.equals(jobDivision.getJobId())) {
        leaveTime = dailyWorkingTimeInfo.getPaidHoliday();
      }
    }
    form.setLeaveTime(leaveTime);
    
    return errors;
  }

  /**
   * Gets the attendance setting list.
   * 
   * @return the attendance setting list
   * @throws SQLException the sQL exception
   */
  public List<LabelValueBean> getAttendanceSettingList() throws SQLException {
    List<Job> jobList = getJobDAO().getUsingJobList();

    List<LabelValueBean> result = new ArrayList<LabelValueBean>();
    for (Job job : jobList) {
      LabelValueBean item = new LabelValueBean(job.getJobName(), job.getJobId());
      result.add(item);
    }
    return result;
  }

  /**
   * Gets the time setting list.
   * 
   * @return the time setting list
   * @throws SQLException the sQL exception
   */
  public List<LabelValueBean> getTimeSettingList() throws SQLException {
    List<WorkingTimeMaster> wtmList = getWorkingTimeMasterDAO().getAllWorkingTimeMaster();

    List<LabelValueBean> result = new ArrayList<LabelValueBean>();
    for (WorkingTimeMaster wtm : wtmList) {
      LabelValueBean item = new LabelValueBean();
      item.setValue(wtm.getWorkingTimeId());
      item.setLabel(wtm.getWorkingtimeName());
      result.add(item);
    }

    return result;
  }

}
